<!DOCTYPE html>
<meta charset="utf-8">
<title>Zoom + Pan</title>
<style>

 body {
     position: relative;
 }

 svg {
     font: 10px sans-serif;
 }

 rect {
     fill: #ddd;
 }

 .axis path,
 .axis line {
     fill: none;
     stroke: #000;
 }

 button {
     position: absolute;
     right: 30px;
     top: 30px;
 }

 .tooltip {
     background: #eee;
     box-shadow: 0 0 5px #999999;
     position: absolute;
     padding: 10px;
     color: #333;
     display: none;
 }

 .tooltip pre {
     padding: 0px;
 }

 .highlight {
     filter: brightness(3);
     box-shadow: 0 0 5px #999999;
     color: red;
     fill-opacity: 0.5;
 }

</style>
<button>Reset</button>
<script src="//d3js.org/d3.v3.js"></script>
<script>
var data = $PROFILER_DATA;
</script>
<script>

 var margin = {top: 20, right: 20, bottom: 30, left: 100},
     width = parseInt(d3.select('body').style('width')) - margin.left - margin.right,
     height = 500 - margin.top - margin.bottom;

 var colorOf = d3.scale.category20();

 var x = d3.scale.linear()
           .domain([0, width])
           .range([0, width]);

 var y = d3.scale.ordinal()
           .rangeRoundBands([height, 0], 0.3);

 var xAxis = d3.svg.axis()
               .scale(x)
               .orient("bottom");

 var yAxis = d3.svg.axis()
               .scale(y)
               .orient("left")
               .ticks(5);

 var zoom = d3.behavior.zoom()
              .x(x)
              .scaleExtent([1.0, 20])
              .on("zoom", zoomed);

 var svg = d3.select("body")
             .append("svg")
             .attr("width", width + margin.left + margin.right)
             .attr("height", height + margin.top + margin.bottom)
             .append("g")
             .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
             .call(zoom);

 var tooltip = d3.select('body')
                 .append('div')
                 .attr('class', 'tooltip');

 svg.append("rect")
    .attr("width", width)
    .attr("height", height);

 var plot = svg.append("svg")
               .append("g")
               .attr("id", "plot");

 data = data.map(type);
 console.log(data);
 var unique = function(a) {
     return a.reduce(function(p, c) {
         if (p.indexOf(c) < 0) p.push(c);
         return p;
     }, []);
 };

 var names = data.map(function(d) { return d.name; });
 names = unique(names);
 names.sort();
 names.reverse();
 console.log(names);

 y.domain(names);

 var xmin = d3.min(data, function(d) { return d.start; });
 var xmax = d3.max(data, function(d) { return d.end; });
 x.domain([xmin, xmax]);
 zoom.x(x);

 colorOf.domain(names);

 svg.append("g")
     .attr("class", "x axis")
     .attr("transform", "translate(0," + height + ")")
     .call(xAxis);

 svg.append("g")
     .attr("class", "y axis")
     .call(yAxis);

 plot.selectAll(".bar")
     .data(data)
     .enter().append("rect")
     .attr("class", "bar")
     .attr("y", function(d) { return y(d.name); })
     .attr("height", y.rangeBand())
     .attr("x", function(d) { return x(d.start); })
     .attr("width", function(d) { return Math.max(0.05, x(d.end) - x(d.start)); } )
     .style("fill", function(d) { return colorOf(d.name); })

     .on('mouseover', function(d) {
         d3.select(this).classed("highlight", true);

         var s = "";
         for (k in d) {
             s += k + ": " + d[k] + "<br>";
         }

         tooltip.html("<tt>" + s + "</tt>")
             .style('display', 'block')
             .style('top', (d3.event.pageY - 10) + 'px')
             .style('left', (d3.event.pageX + 20) + 'px');
         })
     .on('mouseout', function(d) {
         d3.select(this).style("stroke", "");
         d3.select(this).classed("highlight", false);
         tooltip.style('display', 'none');
         });

 function type(d) {
     d.elapsed = d.end - d.start;
     return d;
 }

 d3.select("button").on("click", reset);

 function zoomed() {
     var tx = Math.min(0, d3.event.translate[0]);
     plot.attr("transform", "translate(" + tx + ",0)" + " scale(" + d3.event.scale + ",1)");
     zoom.translate([tx, 0]);

     svg.select(".x.axis").call(xAxis);
 }

 function reset() {
     d3.transition().duration(750).tween("zoom", function() {
         var ix = d3.interpolate(x.domain(), [-width / 2, width / 2]),
         iy = d3.interpolate(y.domain(), [-height / 2, height / 2]);
         return function(t) {
             zoom.x(x.domain(ix(t))).y(y.domain(iy(t)));
             zoomed();
         };
     });
 }



 function murmurhash3_32_gc(key, seed) {
     var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;

     remainder = key.length & 3; // key.length % 4
     bytes = key.length - remainder;
     h1 = seed;
     c1 = 0xcc9e2d51;
     c2 = 0x1b873593;
     i = 0;

     while (i < bytes) {
	 k1 =
	 ((key.charCodeAt(i) & 0xff)) |
	 ((key.charCodeAt(++i) & 0xff) << 8) |
	 ((key.charCodeAt(++i) & 0xff) << 16) |
	 ((key.charCodeAt(++i) & 0xff) << 24);
	 ++i;

	 k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
	 k1 = (k1 << 15) | (k1 >>> 17);
	 k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;

	 h1 ^= k1;
         h1 = (h1 << 13) | (h1 >>> 19);
	 h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
	 h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
     }

     k1 = 0;

     switch (remainder) {
	 case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
	 case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
	 case 1: k1 ^= (key.charCodeAt(i) & 0xff);

	     k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
	     k1 = (k1 << 15) | (k1 >>> 17);
	     k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
	     h1 ^= k1;
     }

     h1 ^= key.length;

     h1 ^= h1 >>> 16;
     h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
     h1 ^= h1 >>> 13;
     h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
     h1 ^= h1 >>> 16;

     return h1 >>> 0;
 }
</script>
